<?php
/**
 * Framework_DB_Common n
 *
 * @author      Ian Szewczyk <roamzero@gmail.com>
 * @copyright   (c) 2007 Ian Szewczyk. All rights reserved.
 * @license     http://www.opensource.org/licenses/bsd-license.php
 * @package Framework
 * @subpackage DB
 * @filesource
 */

require_once 'DB/Table/Database.php';


/**
 * Framework_DB_Common 
 *
 * Base DB class
 *
 * @author 		Ian Szewczyk <roamzero@gmail.com>
 * @package 	Framework
 * @subpackage 	DB
 */

abstract class Framework_DB_Common { //extends Framework_Object_DB  {

	/**
     * $tables
     *
     * @access      public
     * @var         array       $tables
     */
	public $tables = array();

	/**
     * $refs
     *
     * @access      protected
     * @var         array       $tables
     */
	protected $refs = array();

	/**
     * $sql
     *
     * @access      protected
     * @var         array       $tables
     */
	protected $sql = array();

	/**
     * $links
     *
     * @access      protected
     * @var         array       $tables
     */
	protected $links = array();

	/**
     * $database
     *
     * @access      public
     * @var         object       $database Instance of DB_Table_Database
     */
	public $database;

	/**
     * __construct
     *
     * @access      public
     * @return      void
     */
	public function __construct($name)
	{

		$result = new DB_Table_Database(Framework_DB::getDBConnection(),$name);

		if($result->error) {
			throw new Framework_Exception($result->error);
		} else {
			$this->database = $result;

			$this->database->fetchmode = MDB2_FETCHMODE_ASSOC;



			// assign SQL
			$this->database->sql = $this->sql;



			// set subclass directory
			$this->database->setTableSubclassPath('Framework/DB/Table');
		}
	}

	/**
     * update
     *
     * Update data in the database
     *
     * @access      public
     * @param       string      $table_name		Name of the table
     * @param       array     	$data		Data for the update
     * @param       mixed     	$where		Where clause
     * @return      mixed
     * @see         DB_Table_Database::update
     */
	public function update($table_name, $data, $where)
	{
		// add table if it doesnt exist
		if (!array_key_exists($table_name, $this->database->_table)) {
			$this->database->addTable(Framework_DB::tableFactory($table_name));
		}

		// add refs first
		foreach($this->refs as $ref) {
			if($ref['rtable'] == $table_name) {
				if (!array_key_exists($ref['ftable'], $this->database->_table)) {
					$this->database->addTable(Framework_DB::tableFactory($ref['ftable']));
				}
				$this->database->addRef($ref['ftable'], $ref['fkey'], $ref['rtable'], $ref['rkey'], $ref['on_delete'], $ref['on_update']);
			}
		}

		return $this->database->update($table_name, $data, $where);

	}

	/**
     * delete
     *
     * Delete data in the database
     *
     * @access      public
     * @param       string      $table_name		Name of the table
     * @param       mixed     	$where		Where clause
     * @return      mixed
     * @see         DB_Table_Database::delete
     */
	public function delete($table_name, $where)
	{
		// add table if it doesnt exist
		if (!array_key_exists($table_name, $this->database->_table)) {
			$this->database->addTable(Framework_DB::tableFactory($table_name));
		}

		// add refs first
		foreach($this->refs as $ref) {
			if($ref['rtable'] == $table_name) {
				if (!array_key_exists($ref['ftable'], $this->database->_table)) {
					$this->database->addTable(Framework_DB::tableFactory($ref['ftable']));
				}
				$this->database->addRef($ref['ftable'], $ref['fkey'], $ref['rtable'], $ref['rkey'], $ref['on_delete'], $ref['on_update']);
			}
		}

		return $this->database->delete($table_name, $where);

	}



	/**
     * Autojoin
     *
     * Automatically creates joined SQL statement based only on input parameters
     *
     * @access      public
     * @param       array       $cols		Array of column names
     * @param       array     	$tables		Array of table names
     * @param       string     	$filter	    Filter added to SQL
     * @return      mixed
     * @see         DB_Table_Database::autoJoin
     */
	public function autoJoin($cols = null, $tables = null, $filter = null)
	{
		foreach($tables AS $table) {
			if (!array_key_exists($table, $this->database->_table)) {
				$this->database->addTable(Framework_DB::tableFactory($table));
			}
		}

		return $this->database->autoJoin($cols, $tables, $filter);

	}
	
	/**
     * select
     *
     * Data to select from database
     *
     * @access      public
     * @param       array       $args		Query array
     * @param       mixed     	$cacheHandler		Cache Handler object for loggin table dependencies
     * @return      mixed
     * @see         DB_Table_Database::select
     */
	public function select($args, $cacheHandler = null)
	{

		if (is_array($args['sqlKey'])) {
			$sqlKey = $args['sqlKey'];
		} else {
			$sqlKey = $this->sql[$args['sqlKey']];
		}
		$tables = split(',' ,$sqlKey['from']);


		foreach($tables AS $table) {
			if (!array_key_exists($table, $this->database->_table)) {
				$this->database->addTable(Framework_DB::tableFactory(trim($table)));
			}
		}
			
		if (is_array($args['filter'])) {
			$args['filter'] = DB_Table_Database::buildFilter($args['filter'] );
		}
		
		
		if ($cacheHandler  && $cacheHandler instanceof Framework_Cache_Handler_Common) {
			if ($tables) {
				Framework_DB::logDependency($cacheHandler,$tables);
			}
		}
		return $this->database->select($args['sqlKey'], $args['filter'], $args['order'], $args['start'], $args['count'], $args['params']);
	}

	/**
     * selectCount
     *
     * Get the number of rows a query would return
     *
     * @access      public
     * @param       array       $args		Query array
     * @param       mixed     	$cacheHandler		Cache Handler object for loggin table dependencies
     * @return      mixed
     * @see         DB_Table_Database::selectCount
     */
	public function selectCount($args, $cacheHandler = null)
	{

		if (is_array($args['sqlKey'])) {
			$sqlKey = $args['sqlKey'];
		} else {
			$sqlKey = $this->sql[$args['sqlKey']];
		}
		$tables = split(',' ,$sqlKey['from']);

		foreach($tables AS $table) {
			if (!array_key_exists($table, $this->database->_table)) {
				
				$this->database->addTable(Framework_DB::tableFactory(trim($table)));
			}
		}
			
		if (is_array($args['filter'])) {
			$args['filter'] = DB_Table_Database::buildFilter($args['filter'] );
		}

		if ($cacheHandler  && $cacheHandler  instanceof Framework_Cache_Handler_Common) {
			if ($tables) {

				Framework_DB::logDependency($cacheHandler,$tables);
			}
		}

		return  $this->database->selectCount($args['sqlKey'], $args['filter'], $args['order'], $args['start'], $args['count'], $args['params']);
	}

	/**
     * selectResult
     *
     * Returns a result object to manualy get rows from the result set
     *
     * @access      public
     * @param       array       $args		Query array
     * @param       mixed     	$cacheHandler		Cache Handler object for loggin table dependencies
     * @return      mixed
     * @see         DB_Table_Database::selectResult
     */
	public function selectResult($args,$cacheHandler = null)
	{
			
		if (is_array($args['sqlKey'])) {
			$sqlKey = $args['sqlKey'];
		} else {
			$sqlKey = $this->sql[$args['sqlKey']];
		}
		$tables = split(',' ,$sqlKey['from']);

		foreach($tables AS $table) {
			
			if (!array_key_exists($table, $this->database->_table)) {
				$this->database->addTable(Framework_DB::tableFactory(trim($table)));
			}
		}
			
		if (is_array($args['filter'])) {
			$args['filter'] = DB_Table_Database::buildFilter($args['filter'] );
		}

		if ($cacheHandler  && $cacheHandler  instanceof Framework_Cache_Handler_Common) {
			if ($tables) {

				Framework_DB::logDependency($cacheHandler,$tables);
			}
		}
		return  $this->database->selectResult($args['sqlKey'], $args['filter'], $args['order'], $args['start'], $args['count'], $args['params']);
	}

	
	/**
     * getTable
     *
     * Returns a table object
     *
     * @access      public
     * @param       string       $name		Name of table
     * @return      mixed
     * @see         DB_Table_Database::getTable
     */
	public function getTable($name = null) 
    {
    	if ($name && !array_key_exists($name, $this->database->_table)) {
			$this->database->addTable(Framework_DB::tableFactory($name));
		}
		
		return $this->database->getTable($name);
    }
    
    /**
     * __call
     *
     * Routes function calls to the internal database object
     *
     * @access      public
     * @param       string      $function		Name of function
     * @param       array       $args		Array of arguments
     * @return      mixed
     */
    public function __call($function, $args)
	{
		return call_user_func_array(array(&$this->database,$function),$args);
	}

	/**
     * __sleep
     *
     * invoked upon serialization
     *
     * @access      public
	 * @return      array
     */
	public function __sleep()
	{
		$this->database->_table = array();
		$this->database->_db = null;
		$this->database->sql = null;
		$this->database->_link = array();
		$this->database->_ref = array();
		$this->database->_ref_to = array();
		$this->database = serialize($this->database);
		return(array_keys(get_object_vars($this)));
	}


	/**
     * __wakeup
     *
     * invoked upon unserialization
     *
     * @access      public
	 * @return      void
     */
	public function __wakeup()
	{
		$this->database = unserialize($this->database);
		$this->database->sql =& $this->sql;
		$this->database->setDBconnection(Framework_DB::getDBConnection());
		// set subclass directory
		$this->database->setTableSubclassPath('Framework/DB/Table');
	}

}
?>